RDS for SQL ServerでKerberos認証を使う条件について

RDS for SQL ServerでKerberos認証を使う条件について

Clock Icon2023.07.29

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

しばたです。

前回の記事でRDS for SQL ServerがセルフマネージドなActive Directoryドメインに参加した場合はNTLM認証のみ可能な旨を説明しました。

https://dev.classmethod.jp/articles/rds-for-sqlserver-supports-self-managed-ad/

記事を書いている途中で「従来のAWS Managed Microsoft ADドメインに参加した場合はどうだっけ?詳しく調べたこと無いな。」となったので実際に調べてみました。

SQL ServerでKerberos認証が使われる条件

RDS for SQL Serverの話をするまえにSQL Serverの仕様を確認しておきます。
SQL ServerでKerberos認証が使われる条件は以下のドキュメントに記載されています。

SQL Server で Kerberos 認証を使用するには、次の両方の条件が満たされる必要があります。

  • クライアント コンピューターとサーバー コンピューターが、同じ Windows ドメインまたは信頼関係のあるドメインの一部であることが必要です。

  • SPN (サービス プリンシパル名) は、Windows ドメインのキー配布センターの役割を担う Active Directory に登録されることが必要です。 SPN は、登録後に、SQL Server インスタンス サービスを起動した Windows アカウントに対してマップされます。 SPN 登録がまだ実行されていないか失敗した場合、Windows セキュリティ レイヤーでは SPN に関連するアカウントを決定することができず、Kerberos 認証は使用されません。

重要なのは後者のほうで「適切なSPNが登録されていなければKerberos認証は使われずNTLM認証にフォールバックする」仕様となっています。

RDSは通常独自のDNSエンドポイント(rds.amazonaws.comなホスト名)に対して接続します。
すると「そもそも適切なSPNが登録されていないのでは?常にNTLM認証しかしないのでは?」という疑問が湧いてきます。

AWS Managed Microsoft AD ドメインに参加した場合

ということで、まずはAWS Managed Microsoft AD環境を用意してRDSインスタンスをドメインに参加させ挙動を確認してみました。

新規にcorp2.contoso.comドメイン[1]を用意し、RDS for SQL Serverインスタンスを参加させてます。併せて管理用EC2インスタンスも用意しておきました。

(mydb2がAWS Managed Microsoft AD参加のインスタンス。mydbは前回使用したセルフマネージドAD参加インスタンス。)

この状態で管理用EC2インスタンスからSPNの登録状況を調査すると以下の様になりました。

# SQL Server (MSSQLSvc) 用SPNを検索
PS C:\> setspn -T * -F -Q MSSQLSvc/*
フォレスト DC=corp2,DC=contoso,DC=com を確認しています
CN=EC2AMAZ-OI56D18,OU=RDS,OU=AWS Reserved,DC=corp2,DC=contoso,DC=com
        MSSQLSvc/mydb2.corp2.contoso.com:1433
        MSSQLSvc/EC2AMAZ-OI56D18.corp2.contoso.com:1433
        MSServerClusterMgmtAPI/EC2AMAZ-OI56D18
        MSServerClusterMgmtAPI/EC2AMAZ-OI56D18.corp2.contoso.com
        MSSQLSvc/EC2AMAZ-OI56D18.corp2.contoso.com
        TERMSRV/EC2AMAZ-OI56D18
        TERMSRV/EC2AMAZ-OI56D18.corp2.contoso.com
        RestrictedKrbHost/EC2AMAZ-OI56D18
        HOST/EC2AMAZ-OI56D18
        RestrictedKrbHost/EC2AMAZ-OI56D18.corp2.contoso.com
        HOST/EC2AMAZ-OI56D18.corp2.contoso.com

RDS for SQL Serverインスタンスの実体(EC2AMAZ-OI56D18)にSPNの登録があることが分かります。
このインスタンスに絞って検索すると以下の結果になります。

# EC2AMAZ-OI56D18 に絞ってSPNを表示
PS C:\> setspn -L EC2AMAZ-OI56D18
次の項目に登録されている CN=EC2AMAZ-OI56D18,OU=RDS,OU=AWS Reserved,DC=corp2,DC=contoso,DC=com:
        MSSQLSvc/mydb2.corp2.contoso.com:1433
        MSSQLSvc/EC2AMAZ-OI56D18.corp2.contoso.com:1433
        MSServerClusterMgmtAPI/EC2AMAZ-OI56D18
        MSServerClusterMgmtAPI/EC2AMAZ-OI56D18.corp2.contoso.com
        MSSQLSvc/EC2AMAZ-OI56D18.corp2.contoso.com
        TERMSRV/EC2AMAZ-OI56D18
        TERMSRV/EC2AMAZ-OI56D18.corp2.contoso.com
        RestrictedKrbHost/EC2AMAZ-OI56D18
        HOST/EC2AMAZ-OI56D18
        RestrictedKrbHost/EC2AMAZ-OI56D18.corp2.contoso.com
        HOST/EC2AMAZ-OI56D18.corp2.contoso.com

インスタンスの実体となる

  • MSSQLSvc/EC2AMAZ-OI56D18.corp2.contoso.com:1433

以外に

  • MSSQLSvc/mydb2.corp2.contoso.com:1433

という行があることが分かります。
これはRDS for SQL Server側で専用のホスト名[DB識別子].[ドメインFQDN]をエイリアス(CNAME)として提供しているものになります。

# CNAMEの実体は EC2AMAZ-OI56D18.corp2.contoso.com 
PS C:\> nslookup mydb2.corp2.contoso.com
サーバー:  corp2.contoso.com
Address:  10.0.21.30

名前:    EC2AMAZ-OI56D18.corp2.contoso.com
Address:  10.0.21.15
Aliases:  mydb2.corp2.contoso.com

AWSのドキュメントでは自分で作る様な書き方をしていますが、実際には自動で作成されていました。

Kerberos-based authentication requires that the endpoint be the customer-specified host name, a period, and then the fully qualified domain name (FQDN). For example, the following is an example of an endpoint you might use with Kerberos-based authentication. In this example, the SQL Server DB instance host name is ad-test and the domain name is corp-ad.company.com.

当然RDSのDNSエンドポイントに対するSPNはありません。
このため以下の結果になることが予想されます。

  • RDSのエンドポイント(mydb2.xxxxxx.ap-northeast-1.rds.amazonaws.com) → NTLM認証
  • エイリアスのDNS名 (mydb2.corp2.contoso.com) → Kerberos認証
  • インスタンスの実体 (EC2AMAZ-OI56D18.corp2.contoso.com) → Kerberos認証

それぞれのホスト名に対し接続した結果は以下の通りです。

# sqlcmdコマンドで接続確認
sqlcmd -S mydb2.xxxxxx.ap-northeast-1.rds.amazonaws.com -H "EC2 (rds.amazonaws.com)"
sqlcmd -S mydb2.corp2.contoso.com -H "EC2 (mydb2.corp2.contoso.com)"
sqlcmd -S EC2AMAZ-OI56D18.corp2.contoso.com -H "EC2 (EC2AMAZ-OI56D18.corp2.contoso.com)"

(識別しやすい様にホスト名-Hを個別に変えて接続)

(それぞれのセッション情報を取得)

ばっちり予想通りの結果となりました。

セルフマネージドなActive Directoryドメインに参加した場合

こちらは前回記事の環境corp.contoso.comドメインとRDSインスタンスをそのまま使います。

ドメインコントローラーからSPNの登録状況を調査すると以下の様になりました。

# SQL Server (MSSQLSvc) 用SPNを検索
PS C:\> setspn -T * -F -Q MSSQLSvc/*
フォレスト DC=corp,DC=contoso,DC=com を確認しています
CN=EC2AMAZ-06CNSE2,OU=RDSInstances,DC=corp,DC=contoso,DC=com
        # ・・・省略・・・
CN=EC2AMAZ-1K2JSBE,OU=RDSInstances,DC=corp,DC=contoso,DC=com
        # ・・・省略・・・
CN=EC2AMAZ-6HMJA86,OU=RDSInstances,DC=corp,DC=contoso,DC=com
        # ・・・省略・・・
CN=EC2AMAZ-FD531AP,OU=RDSInstances,DC=corp,DC=contoso,DC=com
        # ・・・省略・・・
CN=EC2AMAZ-PN76CIR,OU=RDSInstances,DC=corp,DC=contoso,DC=com
        # ・・・省略・・・
CN=EC2AMAZ-QRTV9CT,OU=RDSInstances,DC=corp,DC=contoso,DC=com
        # ・・・省略・・・

検証作業で何度もRDSインスタンスの停止・再起動を繰り返したためその分すべての内容が残っていました。
(ゴミとなったコンピューターオブジェクトも残っている...)

この時点でのインスタンスの実体はEC2AMAZ-06CNSE2のため、対象を絞った結果は以下の通りです。

# EC2AMAZ-06CNSE2 に絞ってSPNを表示
# 一件SPNはあるが、ポート番号の記載が無い
PS C:\> setspn -L EC2AMAZ-06CNSE2
次の項目に登録されている CN=EC2AMAZ-06CNSE2,OU=RDSInstances,DC=corp,DC=contoso,DC=com:
        MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com
        MSServerClusterMgmtAPI/EC2AMAZ-06CNSE2
        MSServerClusterMgmtAPI/EC2AMAZ-06CNSE2.corp.contoso.com
        TERMSRV/EC2AMAZ-06CNSE2
        TERMSRV/EC2AMAZ-06CNSE2.corp.contoso.com
        WSMAN/EC2AMAZ-06CNSE2
        WSMAN/EC2AMAZ-06CNSE2.corp.contoso.com
        RestrictedKrbHost/EC2AMAZ-06CNSE2
        HOST/EC2AMAZ-06CNSE2
        RestrictedKrbHost/EC2AMAZ-06CNSE2.corp.contoso.com
        HOST/EC2AMAZ-06CNSE2.corp.contoso.com

セルフマネージドなADではCNAMEの自動作成は行われません。
また、AWS Managed Microsoft AD環境と同様にインスタンスの実体となる

  • MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com

の記述はありますが、AWS Managed Microsoft AD環境と異なりポート番号は記載されていません。
ドキュメントによればポート番号が無いものはTPC以外のプロトコル用とのことで、これはダメな予感がします。

TCP 以外のプロトコルが使用される場合に、既定のインスタンスに対してプロバイダーが生成する既定の SPN。<FQDN> は、完全修飾ドメイン名です。

ということで、予想としては

  • RDSのエンドポイント(mydb2.xxxxxx.ap-northeast-1.rds.amazonaws.com) → NTLM認証
  • インスタンスの実体 (EC2AMAZ-06CNSE2.corp.contoso.com) → NTLM認証

になり、実際結果もその通りでした。

sqlcmd -S mydb.xxxxxx.ap-northeast-1.rds.amazonaws.com -H "ADDS (rds.amazonaws.com)"
sqlcmd -S EC2AMAZ-06CNSE2.corp.contoso.com -H "ADDS (EC2AMAZ-06CNSE2.corp.contoso.com)"

(識別しやすい様にホスト名-Hを個別に変えて接続)

(それぞれのセッション情報を取得)

AWSの言う通りセルフマネージドなADに参加した場合は常にNTLM認証が使われます。

結果まとめ

ここまでの結果を表にまとめました。

ディレクトリ種別 接続先ホスト名 認証方式 備考
AWS Managed Microsoft AD RDSのDNSエンドポイント([DB識別子].xxxxxx.[リージョン名].rds.amazonaws.com) NTLM認証 SPN無し
AWS Managed Microsoft AD エイリアスのDNS名 ([DB識別子].[ドメインFQDN]) Kerberos認証 AWS Managed Microsoft ADが自動で用意してくれるCNAME
AWS Managed Microsoft AD 実体のEC2インスタンス ([EC2AMAZ-XXXXXXX].[ドメインFQDN]) Kerberos認証 非推奨
セルフマネージドなAD RDSのDNSエンドポイント([DB識別子].xxxxxx.[リージョン名].rds.amazonaws.com) NTLM認証 SPN無し
セルフマネージドなAD 実体のEC2インスタンス ([EC2AMAZ-XXXXXXX].[ドメインFQDN]) NTLM認証 非推奨

AWS Managed Microsoft AD環境でエイリアスのDNS名と実体となるEC2ホスト名を指定したときだけKerberos認証が使えます。

ただし、実体となるEC2ホスト名は結構頻繁に変わりうるので運用環境での利用はお勧めできません。
(どうやらRDSの起動・停止の都度変わっている、EC2インスタンスがすげ替えられる様な挙動をしている...)
エイリアスのDNS名は実体のEC2インスタンスが切り替わった場合でも追従して更新されたのでこちらを使う様にしてください。

余談 : むりやりSPNを設定してみる (非サポート/無保証)

ここまでくると「セルフマネージドなAD環境でも自分でSPNを設定すればKerberos認証できるのでは?」と考えるのは必然です。

ということで実際やってみました。

インスタンスの実体に対するSPNを追加

まずはインスタンスの実体EC2AMAZ-06CNSE2.corp.contoso.comに対するSPNを追加してみます。

# ポート番号付きのSPNを登録する
setspn -S MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com:1433 EC2AMAZ-06CNSE2

実行結果はこの様になり、ポート番号付きの行が増えました。

PS C:\> setspn -S MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com:1433 EC2AMAZ-06CNSE2
ドメイン DC=corp,DC=contoso,DC=com を確認しています

CN=EC2AMAZ-06CNSE2,OU=RDSInstances,DC=corp,DC=contoso,DC=com の ServicePrincipalNames を登録しています
        MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com:1433
更新されたオブジェクト
PS C:\> setspn -L EC2AMAZ-06CNSE2
次の項目に登録されている CN=EC2AMAZ-06CNSE2,OU=RDSInstances,DC=corp,DC=contoso,DC=com:
        MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com:1433
        MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com
        MSServerClusterMgmtAPI/EC2AMAZ-06CNSE2
        MSServerClusterMgmtAPI/EC2AMAZ-06CNSE2.corp.contoso.com
        TERMSRV/EC2AMAZ-06CNSE2
        TERMSRV/EC2AMAZ-06CNSE2.corp.contoso.com
        WSMAN/EC2AMAZ-06CNSE2
        WSMAN/EC2AMAZ-06CNSE2.corp.contoso.com
        RestrictedKrbHost/EC2AMAZ-06CNSE2
        HOST/EC2AMAZ-06CNSE2
        RestrictedKrbHost/EC2AMAZ-06CNSE2.corp.contoso.com
        HOST/EC2AMAZ-06CNSE2.corp.contoso.com

これはいけそうな気がします。
この状態で接続確認してみるとKerberos認証で接続してくれました。

いい感じです。

ちなみに追加したSPNを削除する際は以下のコマンドを実行します。

# setspn -D でSPNを削除
setspn -D MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com:1433 EC2AMAZ-06CNSE2

CNAMEレコードも追加してみた

続けてDNSにCNAMEレコードを追加してAWS Managed Micrsoft ADと同様のことをやっていきます。
今回はrdssql.corp.contoso.comというエイリアスを作ってみます。

# 結果はこんな感じ
PS C:\> nslookup rdssql
サーバー:  localhost
Address:  ::1

名前:    EC2AMAZ-06CNSE2.corp.contoso.com
Address:  10.0.21.239
Aliases:  rdssql.corp.contoso.com

さらにこのホスト名に対するSPNを作成します。

# rdssql.corp.contoso.comに対するSPNを追加
setspn -S MSSQLSvc/rdssql.corp.contoso.com:1433 EC2AMAZ-06CNSE2

最終的な結果は以下の通りです。

PS C:\> setspn -S MSSQLSvc/rdssql.corp.contoso.com:1433 EC2AMAZ-06CNSE2
ドメイン DC=corp,DC=contoso,DC=com を確認しています

CN=EC2AMAZ-06CNSE2,OU=RDSInstances,DC=corp,DC=contoso,DC=com の ServicePrincipalNames を登録しています
        MSSQLSvc/rdssql.corp.contoso.com:1433
更新されたオブジェクト
PS C:\> setspn -L EC2AMAZ-06CNSE2
次の項目に登録されている CN=EC2AMAZ-06CNSE2,OU=RDSInstances,DC=corp,DC=contoso,DC=com:
        MSSQLSvc/rdssql.corp.contoso.com:1433
        MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com:1433
        MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com
        MSServerClusterMgmtAPI/EC2AMAZ-06CNSE2
        MSServerClusterMgmtAPI/EC2AMAZ-06CNSE2.corp.contoso.com
        TERMSRV/EC2AMAZ-06CNSE2
        TERMSRV/EC2AMAZ-06CNSE2.corp.contoso.com
        WSMAN/EC2AMAZ-06CNSE2
        WSMAN/EC2AMAZ-06CNSE2.corp.contoso.com
        RestrictedKrbHost/EC2AMAZ-06CNSE2
        HOST/EC2AMAZ-06CNSE2
        RestrictedKrbHost/EC2AMAZ-06CNSE2.corp.contoso.com
        HOST/EC2AMAZ-06CNSE2.corp.contoso.com

これでrdssql.corp.contoso.comに対して接続してやるとKerberos認証になりました。

sqlcmd -S rdssql.corp.contoso.com -H "ADDS (rdssql.corp.contoso.comm)"

RDSのDNSエンドポイントにSPNを追加してみた

最後にRDSのDNSエンドポイントに対するSPNを追加してみます。

# RDSのDNSエンドポイントに対するSPNを追加
setspn -S MSSQLSvc/mydb.xxxxxx.ap-northeast-1.rds.amazonaws.com:1433 EC2AMAZ-06CNSE2

出来ないと思っていたのですが実際やってみると可能でした。

PS C:\> setspn -S MSSQLSvc/mydb.xxxxxx.ap-northeast-1.rds.amazonaws.com:1433 EC2AMAZ-06CNSE2
ドメイン DC=corp,DC=contoso,DC=com を確認しています

CN=EC2AMAZ-06CNSE2,OU=RDSInstances,DC=corp,DC=contoso,DC=com の ServicePrincipalNames を登録しています
        MSSQLSvc/mydb.xxxxxx.ap-northeast-1.rds.amazonaws.com:1433
更新されたオブジェクト
PS C:\> setspn -L EC2AMAZ-06CNSE2
次の項目に登録されている CN=EC2AMAZ-06CNSE2,OU=RDSInstances,DC=corp,DC=contoso,DC=com:
        MSSQLSvc/mydb.xxxxxx.ap-northeast-1.rds.amazonaws.com:1433
        MSSQLSvc/rdssql.corp.contoso.com:1433
        MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com:1433
        MSSQLSvc/EC2AMAZ-06CNSE2.corp.contoso.com
        MSServerClusterMgmtAPI/EC2AMAZ-06CNSE2
        MSServerClusterMgmtAPI/EC2AMAZ-06CNSE2.corp.contoso.com
        TERMSRV/EC2AMAZ-06CNSE2
        TERMSRV/EC2AMAZ-06CNSE2.corp.contoso.com
        WSMAN/EC2AMAZ-06CNSE2
        WSMAN/EC2AMAZ-06CNSE2.corp.contoso.com
        RestrictedKrbHost/EC2AMAZ-06CNSE2
        HOST/EC2AMAZ-06CNSE2
        RestrictedKrbHost/EC2AMAZ-06CNSE2.corp.contoso.com
        HOST/EC2AMAZ-06CNSE2.corp.contoso.com

そしてKerberos認証による接続もできました。

sqlcmd -S mydb.xxxxxx.ap-northeast-1.rds.amazonaws.com -H "ADDS (rds.amazonaws.com)"

意外となんとかなるものです。

なお、AWS Managed Microsoft AD環境で同様の行為をした場合は権限エラーになります。

# AWS Managed Microsoft AD環境では権限が足りず同様の行為は行えない
PS C:\> setspn -S MSSQLSvc/mydb2.xxxxxx.ap-northeast-1.rds.amazonaws.com:1433 EC2AMAZ-OI56D18
ドメイン DC=corp2,DC=contoso,DC=com を確認しています

CN=EC2AMAZ-OI56D18,OU=RDS,OU=AWS Reserved,DC=corp2,DC=contoso,DC=com の ServicePrincipalNames を登録しています
        MSSQLSvc/mydb2.xxxxxx.ap-northeast-1.rds.amazonaws.com:1433
アカウント 'CN=EC2AMAZ-OI56D18,OU=RDS,OU=AWS Reserved,DC=corp2,DC=contoso,DC=com' で SPN を割り当てられませんでした。エラー 0x2098/8344 -> この操作を実行するための十分なアクセス権がありません。

最後に

以上となります。

今回の結果からRDS for SQL ServerでKerberos認証を使うのは限定的な条件でのみ可能であることが分かりました。
普段の利用においてあまり意識することが無いかもしれませんが、認証方式に対して厳密な要件がある場合はご注意ください。

脚注
  1. corp2なのは前回との対比のため ↩︎

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.